﻿#pragma once
#include "zyRes.hpp"
#include "zyLayout.h"
namespace DarkMoonUI {

    class zyWindow : public zyBase {

    public:
        zyWindow() : zyBase() {
            m_obj->setWndProc(zyWindow_WndProc);
            m_obj->setDestroy(zyWindow_Destroy);
        }

        BOOL _CreateWindow(HWND parent, const std::wstring& windowName,
            POINT pos, POINT size, HMENU hMenu, int style, int exStyle, const std::wstring& className);

        BOOL _CreateDialog(HWND parent, const std::wstring& windowName, POINT pos,
            POINT size, int style, int exStyle, const std::wstring& className);

        INT_PTR _LoadDialog(HWND parent, const std::wstring& windowName, POINT pos, POINT size, int style, int exStyle,
            const std::wstring& className);

        BOOL _CreateDialogFromRC(HWND parent, const std::wstring& rcName, const std::wstring& className);

        INT_PTR _LoadDialogFromRC(HWND parent, const std::wstring& rcName, const std::wstring& className);

        BOOL _CreateMDIWindow(HWND parent, const std::wstring& windowName, POINT pos, POINT size, int style, const std::wstring& className) ;

        BOOL _BindWindow(HWND hWnd);

        void _UnbindWindow();

        void 取消绑定();

        //控件边框_相关常量
        int 边框(int Border);

        int addZyStyle(int style);

        int 添加ZY窗口风格(int ZY窗口风格);

        int removeZyStyle(int style);

        int 移除ZY窗口风格(int ZY窗口风格);

        int getZyStyle() const;

        int 取ZY窗口风格() const;

        int setZyStyle(int style);

        int 置ZY窗口风格(int ZY窗口风格);

        BOOL show(int cmdShow = SW_SHOW);

        BOOL 显示窗口(int 显示命令 = SW_SHOW);

        LRESULT sendMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);

        LRESULT postMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);

        LRESULT 发送消息(UINT 消息, WPARAM wParam, LPARAM lParam);

        LRESULT 投递消息(UINT 消息, WPARAM wParam, LPARAM lParam);

        HWND setCapture();

        BOOL releaseCapture();

        HWND 捕获鼠标();

        BOOL 释放鼠标捕获();

        std::wstring getClassName() const;

        std::wstring 取类名() const;

        VOID 置鼠标指针(zyIcon& 参数_光标);
        zyIcon 取鼠标指针();

        BOOL isWindow() const;

        BOOL 是否已创建() const;

        void destroy();

        void 销毁();

        void setFocuse();

        void 获取焦点();

        BOOL isFocuse() const;

        BOOL 是否有焦点() const;

        RECT getClientRect() const;

        RECT 取客户区矩形() const;

        int getClientWidth() const;

        int 取客户区宽度() const;

        int getClientHeight() const;

        int 取客户区高度() const;

        RECT getRect() const;

        RECT 取矩形() const;

        void setReDraw(BOOL redraw);

        void 禁止重画();

        void 允许重画();

        void reDraw(RECT* lpRc = NULL, BOOL erase = TRUE);

        void 重画(BOOL 擦除背景 = TRUE);

        void 部分重画(RECT& 矩型, BOOL 擦除背景 = TRUE);

        void validateRect();

        void 取消重画();

        void updateWindow();

        void 刷新显示();

        void moveWindow(int x, int y, int width, int height, BOOL repaint = TRUE);

        void 置位置大小(int 左边, int 顶边, int 宽度, int 高度, BOOL 重绘 = TRUE);

        void 通知边框改变();

        void setPos(int x, int y, BOOL repaint = TRUE);

        void setSize(int width, int height, BOOL repaint = TRUE);

        void 置位置(int 左边, int 顶边, BOOL 重绘 = TRUE);

        void 置大小(int 宽度, int 高度, BOOL 重绘 = TRUE);

        POINT getPos() const;

        POINT 取位置() const;

        POINT getSize() const;

        POINT 取大小() const;

        BOOL setInsertAfter(int mode = 1);

        // mode: 1:top, 2:bottom, 3:topmost, 4:notopmost, default:top
        BOOL 调整层次(int 调整模式 = 1);

        HWND setParent(HWND parent);

        HWND 置父窗口(HWND 父窗口句柄);

        HWND 取父窗口();

        int 左边(int 参数_左边 = 0, BOOL 参数_是否立即重画 = true);
        int 顶边(int 参数_顶边 = 0, BOOL 参数_是否立即重画 = true);
        int 宽度(int 参数_宽度 = 0, BOOL 参数_是否立即重画 = true);
        int 高度(int 参数_高度 = 0, BOOL 参数_是否立即重画 = true);
        BOOL 可视(BOOL 参数_是否可视 = false);
        BOOL 是否可视();
        BOOL 禁止(BOOL 参数_是否禁止 = false);
        BOOL 是否禁止();

        DWORD GetStyle();
        DWORD SetStyle(DWORD Style);
        DWORD RemoveStyle(DWORD nStyle);
        DWORD AddStyle(DWORD Style);
        //@别名 添加扩展风格()
        DWORD AddExStyle(DWORD ExStyle);
        //@别名 移除扩展风格()
        DWORD RemoveExStyle(DWORD ExStyle);
        //@别名 置扩展风格()
        DWORD SetExStyle(DWORD ExStyle);
        //@别名 取扩展风格()
        DWORD GetExStyle();
        int 取文本长度();
        BOOL 置文本(const std::wstring& bt);

        std::wstring 取文本();
        int 信息框(const std::wstring& 参数_提示信息, int 参数_按钮 = NULL,const std::wstring& 参数_窗口标题 = L"信息:");

        void 置字体(HFONT 参数_字体);
        HFONT 取字体();
        void 允许文件拖放(BOOL 参数_是否允许拖放);
        BOOL 开始时钟(int 参数_时钟周期, int 参数_时钟ID = 1);
        BOOL 停止时钟(int 参数_时钟ID = 1);

        BOOL 置布局(zyLayout& 参数_布局);
        LRESULT 调用默认窗口过程(UINT 参数_msg, WPARAM 参数_wParam, LPARAM 参数_lParam);

        BOOL 置属性(const std::wstring& 参数_属性名, HANDLE 参数_属性值) { return SetProp(取窗口句柄(), 参数_属性名.c_str(), 参数_属性值) != 0; }
        HANDLE 取属性(const std::wstring& 参数_属性名) { return GetProp(取窗口句柄(), 参数_属性名.c_str()); }
        HANDLE 移除属性(const std::wstring& 参数_属性名) { return RemoveProp(取窗口句柄(), 参数_属性名.c_str()); }
        int 取属性名列表(std::vector<std::wstring> 参数_属性名数组);
        int 取属性值列表(std::vector<int> 参数_属性值数组);

        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnMouseMove(HWND hWnd,整型 横坐标,整型 纵坐标,整型 功能键状态)
        void 通用事件_鼠标位置被移动(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnPaint(HWND hWnd,HDC hdc,整型 重画左边,整型 重画顶边,整型 重画右边,整型 重画底边)
        void 通用事件_重画(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnLButtonDown(HWND hWnd,整型 横坐标,整型 纵坐标,整型 功能键状态)
        void 通用事件_鼠标左键被按下(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnLButtonUp(HWND hWnd,整型 横坐标,整型 纵坐标,整型 功能键状态)
        void 通用事件_鼠标左键被放开(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnLButtonDblClk(HWND hWnd,整型 横坐标,整型 纵坐标,整型 功能键状态)
        void 通用事件_被双击(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnRButtonDown(HWND hWnd,整型 横坐标,整型 纵坐标,整型 功能键状态)
        void 通用事件_鼠标右键被按下(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnRButtonUp(HWND hWnd,整型 横坐标,整型 纵坐标,整型 功能键状态)
        void 通用事件_鼠标右键被放开(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnMouseIn(HWND hWnd)
        void 通用事件_鼠标移入(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnMouseHover(HWND hWnd)
        void 通用事件_鼠标悬停(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnMouseLeave(HWND hWnd)
        void 通用事件_鼠标离开(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnSetFocus(HWND hWnd)
        void 通用事件_获取焦点(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnKillFocus(HWND hWnd)
        void 通用事件_失去焦点(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnKeyDown(HWND hWnd,整型 键代码,整型 功能键状态)
        void 通用事件_按下某键(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnKeyUp(HWND hWnd,整型 键代码,整型 功能键状态)
        void 通用事件_放开某键(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnMouseWheel(HWND hWnd,整型 滚动距离,整型 功能键状态)
        void  通用事件_滚轮被滚动(TRegEvent* 参数_事件指针);
        //@事件回调类型 返回值：整型【0表示放行，1表示拦截】int OnChar(HWND hWnd,整型 字符代码)
        void  通用事件_字符输入(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnDropFiles(HWND hWnd,整型 文件路径【Unicode文本指针，以换行符连接】)
        void  通用事件_文件拖放(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnTimer(HWND hWnd,整型 时钟ID)
        void  通用事件_时钟(TRegEvent* 参数_事件指针);
        //@事件回调类型 int OnWndMsg(HWND hWnd,正整型 msg,WPARAM wParam,LPARAM lParam,逻辑型* 已处理)
        void  通用事件_窗口消息(TRegEvent* 参数_事件指针);

    protected:
        bool OnDrawBack(HWND hwnd, HDC hdc);
        void _画图片_废弃(HWND hwnd, HDC hdc, int type, RECT rc, LONG_PTR pBackImage, int BackColor);
        void _画图片(HWND hwnd, HDC hdc, int type, RECT rc, LONG_PTR pBackImage, int BackColor);
        void _SetWindowBorder(int mode, int& style, int& exStyle);
        void _计算居中矩形(int 参数_原图片宽度, int 参数_原图片高度, RECT 参数_原矩形, RECT& 参数_显矩形);
        void 设置窗口边框(int mode, int& style, int& exStyle);
        void _设置控件边框(int 参数_边框, int& 参数_风格, int& 参数_扩展风格);
        static BOOL CALLBACK EnumPropCallback_Name(HWND hwnd, LPWSTR lpszString, HANDLE hData, ULONG_PTR lParam);
        static BOOL CALLBACK EnumPropCallback_Value(HWND hwnd, LPWSTR lpszString, HANDLE hData, ULONG_PTR lParam);
        static void zyWindow_Destroy(zyObject* obj);
        static LRESULT CALLBACK zyWindow_WndProc(zyObject* obj, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL* bHandled);
        BOOL zyWindow_SuperClass(const std::wstring& className, const std::wstring& newClassName);
        static void zyWindow_OnNCDestroy(zyObject* obj);
    private:
        
        static LRESULT CALLBACK zyWindow_OnSetCursor(zyObject* obj, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

        static LRESULT CALLBACK WinProc_SubClass(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

        static LRESULT CALLBACK WinProc_SuperClass(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

        static LRESULT CALLBACK WinProc_Dialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

        static LRESULT CALLBACK WinProc_ModalDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    };
}

// class zyWindow : public zyBase {
// public:
//     bool _CreateWindow(HWND parent,
//                        const std::wstring& windowName,
//                        POINT pos,
//                        POINT size,
//                        HMENU hMenu,
//                        int style,
//                        int exStyle,
//                        const std::wstring& className) {
//         HWND hWnd = getHwnd();
//         if (hWnd)
//             return false;
//         zyAppInfo::getInstance().dpiProcess(pos);
//         zyAppInfo::getInstance().dpiProcess(size);
//         hWnd = CreateWindowExW(exStyle,
//                                className.c_str(), windowName.c_str(),
//                                style,
//                                pos.x, pos.y,
//                                size.x, size.y,
//                                parent, hMenu,
//                                zyAppInfo::getInstance().getModuleHandle(), getObject());
//         return hWnd != nullptr;
//     }

//     bool _CreateDialog(HWND parent,
//                        const std::wstring& windowName,
//                        POINT pos,
//                        POINT size,
//                        HMENU hMenu,
//                        int style,
//                        int exStyle,
//                        const std::wstring& className) {
//         HWND hWnd = getHwnd();
//         if (hWnd)
//             return false;
//         zyAppInfo::getInstance().dpiProcess(pos);
//         zyAppInfo::getInstance().dpiProcess(size);
//         DLGTEMPLATE lpTemplate = {(DWORD)style,
//                                   (DWORD)exStyle,
//                                   0,
//                                   (short)pos.x, (short)pos.y,
//                                   (short)size.x, (short)size.y};
//         size_t nBuffLen = sizeof(DLGTEMPLATE);
//         nBuffLen += windowName.empty() ? 2 : windowName.length() * sizeof(wchar_t);
//         nBuffLen += className.empty() ? 2 : className.length() * sizeof(wchar_t);
//         nBuffLen += 6;
//         char* lpBuff = new char[nBuffLen];
//         memset(lpBuff, 0, nBuffLen);
//         *(LPDLGTEMPLATE)lpBuff = lpTemplate;
//         char* p = lpBuff + sizeof(DLGTEMPLATE);
//         if (!className.empty()) {
//             memcpy(p, className.c_str(), className.length() * sizeof(wchar_t));
//             p += className.length() * sizeof(wchar_t);

//             WNDCLASSEXW wndClass = {sizeof(WNDCLASSEXW)};
//             GetClassInfoExW(zyAppInfo::getInstance().getModuleHandle(), L"32770", &wndClass);
//             wndClass.lpszClassName = className.c_str();
//             RegisterClassExW(&wndClass);
//         }
//         p += 2;
//         if (!windowName.empty())
//             memcpy(p, windowName.c_str(), windowName.length() * sizeof(wchar_t));

//         hWnd = CreateDialogIndirectParamW(zyAppInfo::getInstance().getModuleHandle(),
//                                           (LPCDLGTEMPLATE)lpBuff, parent,
//                                           WinProc_Dialog, (LPARAM)this);
//         delete[] lpBuff;
//         return hWnd != nullptr;
//     }

//     void _SetBorder(LONG_PTR mode, int& style, int& exStyle) {
//         if (hasBorder()) {
//             style = style & (~(WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_DLGFRAME | WS_SIZEBOX));
//             exStyle = exStyle & (~(WS_EX_OVERLAPPEDWINDOW | WS_EX_TOOLWINDOW));
//             switch (mode) {
//             case 0:
//                 style |= WS_POPUP;
//                 break;
//             case 1:
//                 style |= WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_DLGFRAME | WS_SIZEBOX;
//                 exStyle |= WS_EX_WINDOWEDGE;
//                 break;
//             case 2:
//                 style |= WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_DLGFRAME;
//                 exStyle |= WS_EX_WINDOWEDGE;
//                 break;
//             case 3:
//                 style |= WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_DLGFRAME | WS_SIZEBOX;
//                 exStyle |= WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW;
//                 break;
//             case 4:
//                 style |= WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_DLGFRAME;
//                 exStyle |= WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW;
//                 break;
//             case 5:
//                 style |= WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_DLGFRAME | WS_SIZEBOX;
//                 exStyle |= WS_EX_WINDOWEDGE;
//                 break;
//             default:
//                 style |= WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_DLGFRAME;
//                 exStyle |= WS_EX_WINDOWEDGE;
//                 break;
//             }
//         }
//     }

// private:
//     static CALLBACK LRESULT WinProc_Dialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
//         if (uMsg == WM_INITDIALOG) {
//             if (lParam) {
//                 auto oldStyle = GetClassLongPtrW(hWnd, GCL_STYLE);
//                 SetClassLongPtrW(hWnd, GCL_STYLE, oldStyle | CS_HREDRAW | CS_VREDRAW);
//                 ((zyObject*)lParam)->setPtrData(L"Hwnd", hWnd);
//                 zyAppInfo::getInstance().addEventWnd(hWnd, (zyObject*)lParam);
//             }
//         }

//         auto obj = zyAppInfo::getInstance().getEventObject(hWnd);
//         if (obj) {
//             // return obj->handleEvent(hWnd, uMsg, wParam, lParam);
//         }

//         if (uMsg == WM_CLOSE)
//             DestroyWindow(hWnd);
//         return 0;
//     }

//     static CALLBACK LRESULT WinProc_ModalDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
//         if (uMsg == WM_INITDIALOG) {
//             if (lParam) {
//                 auto oldStyle = GetClassLongPtrW(hWnd, GCL_STYLE);
//                 SetClassLongPtrW(hWnd, GCL_STYLE, oldStyle | CS_HREDRAW | CS_VREDRAW);
//                 ((zyObject*)lParam)->setPtrData(L"Hwnd", hWnd);
//                 zyAppInfo::getInstance().addEventWnd(hWnd, (zyObject*)lParam);
//             }
//         }

//         if (uMsg == WM_CLOSE)
//             DestroyWindow(hWnd);
//         return 0;
//     }
// };